using System;
using UnityEngine;

public class DemoOpenHarmonyJSArrayBuffer
{
    private string logString = "";
    private OpenHarmonyJSObject m_ohJSFile = null;
    private OpenHarmonyJSClass m_ohJSArrayBuffer = null;

    public string Test()
    {
        logString = string.Empty;

        TestJSArrayBuffer();

        return logString;
    }

    void TestJSArrayBuffer()
    {
        // fs 相关接口
        // https://docs.openharmony.cn/pages/v4.1/en/application-dev/reference/apis-core-file-kit/js-apis-file-fs.md
        if (m_ohJSFile == null)
            m_ohJSFile = new OpenHarmonyJSObject("FileSystem");
        if (m_ohJSArrayBuffer == null)
            m_ohJSArrayBuffer = new OpenHarmonyJSClass("ArrayBuffer");
        var filePath = Application.persistentDataPath + "/DemoArrayBuffer.dat";

        byte[] data = new byte[] { 1, 2, 3, 30, 20, 10 };
        TestWrite(filePath, data);
        var readData = TestRead(filePath, 1024);
        
        Log($"Read bytes={readData.Length}");
        for (int i = 0; i < data.Length; i++)
        {
            if (data[i] != readData[i])
            {
                Log($"ERROR!!! Byte read mismatch at index={i}. expected={data[i]} got={readData[i]}");
                return;
            }
        }
        Log("Read bytes equal to previously written bytes");
    }

    void TestWrite(string filePath, byte[] data)
    {
        var fd = m_ohJSArrayBuffer.CallStatic<int>("OpenFile", filePath);
        Log($"write.fd={fd}");//file descriptor

        // write buffer to file
        OpenHarmonyJSArrayBuffer buffer = new OpenHarmonyJSArrayBuffer(data.Length);
        buffer.SetValue(data);
        m_ohJSFile.Call("writeSync", fd, buffer);
        Log($"writeSync buffer={ArrayToString(data)}");
        m_ohJSFile.Call("closeSync", fd);
    }

    byte[] TestRead(string filePath, int buffSize)
    {
        var fd = m_ohJSArrayBuffer.CallStatic<int>("OpenFile", filePath);
        Log($"read.fd={fd}");

        OpenHarmonyJSArrayBuffer readBuffer = new OpenHarmonyJSArrayBuffer(buffSize);
        
        var readBytes = m_ohJSFile.Call<int>("readSync", fd, readBuffer);
        byte[] data = new byte[readBytes];
        Array.Copy(readBuffer.GetValue(), 0, data, 0, readBytes);
        Log($"readSync buffer={ArrayToString(data)}");
        m_ohJSFile.Call("closeSync", fd);

        return data;
    }
    
    private string ArgsToString(params object[] args)
    {
        if (args == null || args.Length == 0)
            return "";
        
        var ret = $"{args[0]}";
        for (int i = 1; i < args.Length; i++)
        {
            ret += $", {args[i]}";
        }

        return ret;
    }

    private string ReturnToString(object obj)
    {
        if (obj.GetType().IsArray)
        {
            return ArrayToString(obj as Array);
        }

        return obj.ToString();
    }

    private string ArrayToString(Array array)
    {
        string log = array.Length + ":[";
        for (int i = 0; i < array.Length; i++)
        {
            if (i == 0)
                log += array.GetValue(i);
            else
                log += ", " + array.GetValue(i);
        }

        log += "]";
        return log;
    }

    private void Log(string log)
    {
        Debug.Log(log);
        logString += log.Replace('\0', ' ') + "\n";
    }
}
